/*
 * CS_MARKET_ITEM_BUY.cpp
 *
 *  Created on: 2013. 5. 22.
 *      Author: mega@gamevil.com
 */

#include "../../Command.h"
#include "../../User.h"
#include "../../Proxy.h"
#include "../../GameLog.h"
#include "../../NLogic/Trade.h"
#include "../../NLogic/MailBox.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/VirtualCurrency.h"
#include "../../NResource/Static.h"
#include "../../GameLog.h"

namespace ProjectZ { namespace NCommand {

static void SendFailMarketItemBuy(User * pUser, int res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(res);
	*pAck << static_cast<uint32_t>(0);
	*pAck << pUser->GetCharacterInfo().gold;
	*pAck << pUser->GetVirtualCurrency()->GetZen();
	pAck->MakePacket(CMD_SC_MARKET_ITEM_BUY);
	pUser->Send(pAck);
}

void Command::CS_MARKET_ITEM_BUY(User * pUser, ::Network::Packet * pPacket)
{
	PREPARE_PACKET;

	uint64_t tradeSeq	= 0;
	char classType		= 0;
	char sheetType		= 0;

	*pPacket >> tradeSeq >> classType >> sheetType;

	// 아이템 정보 조회
	NLogic::Trade::TradeItem::Data clsData;
	clsData.item.class_type	= static_cast<int>(classType);
	clsData.item.sub_type	= static_cast<int>(sheetType);

	NLogic::Trade::TradeItem * pTradeItem	= NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->NEW();
	pTradeItem->Open_Normal(tradeSeq, clsData, pUser);

	if (false == pTradeItem->SelectDatabaseTradeItemDetailInfo())
	{
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
		SendFailMarketItemBuy(pUser, ACK_UNKNOWN_ERROR);
		DEBUGLOG("CS_MARKET_ITEM_BUY : false == pTradeItem->SelectDatabaseTradeItemDetailInfo()");
		return;
	}

	// 구매자 정보 세팅
	pTradeItem->GetData().buyer_slot_seq = pUser->GetCharacterInfo().characterseq;


	// 아이템이 이미 판매된 경우
	if (1 == pTradeItem->GetData().status)
	{
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
		SendFailMarketItemBuy(pUser, ACK_MARKET_ALREADY_SELL);
		return;
	}

	// 판매자가 판매 취소한 경우
	if (2 == pTradeItem->GetData().status)
	{
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
		SendFailMarketItemBuy(pUser, ACK_MARKET_SELLER_CANCEL);
		return;
	}

	// 구매 골드 부족
	if (static_cast<int>(pUser->GetCharacterInfo().gold) < pTradeItem->GetData().item_price)
	{
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
		SendFailMarketItemBuy(pUser, ACK_NOT_ENOUGH_GOLD);
		return;
	}

	// 아이템을 판매 상태로 갱신
	if (false == pTradeItem->UpdateDatabaseSoldoutStatus())
	{
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
		SendFailMarketItemBuy(pUser, ACK_DB_ERROR);
		DEBUGLOG("CS_MARKET_ITEM_BUY : false == pTradeItem->UpdateDatabaseSoldoutStatus()");
		return;
	}

	std::string itemName = NResource::Static::InstancePtr()->GetItemResource()->GetItemName(pTradeItem->GetData().item);

	// 판매자에게 대금 메일 발송
	{
		NLogic::MailBox::Mail::Data clsMailData;

		clsMailData.send_user_seq		= 0;
		clsMailData.send_user_nickname	= "GAMEVIL";
		clsMailData.recv_user_seq		= pTradeItem->GetData().reg_user_seq;
		clsMailData.gift_status			= EM_GIFT_GOLD;

		std::string message = NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessageTradeItemSoldout();
		clsMailData.message.Format("[%s]!N%s", itemName.c_str(), message.c_str());

		// 판매 수수료 20% 차감하고 지급
		clsMailData.gold				= pTradeItem->GetData().item_price - (pTradeItem->GetData().item_price * 0.2);

		if (clsMailData.gold <= 0)
			clsMailData.gold = 1;

		// 메일 발송
		if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
		{
			NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
			SendFailMarketItemBuy(pUser, ACK_DB_ERROR);
			DEBUGLOG("CS_MARKET_ITEM_BUY : false == NLogic::NFunction::SendMail");
			return;
		}
	}

	// 구매자에게 구매 아이템 메일 발송하고, 구매자의 골드 차감
	{

		NLogic::MailBox::Mail::Data clsMailData;

		clsMailData.send_user_seq		= 0;
		clsMailData.send_user_nickname	= "GAMEVIL";
		clsMailData.recv_user_seq		= pUser->GetUserSeq();
		clsMailData.gift_status			= EM_GIFT_ITEM;
		clsMailData.item				= pTradeItem->GetData().item;

		std::string message = NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessageTradeItemBuy();
		clsMailData.message.Format("[%s]!N%s", itemName.c_str(), message.c_str());

		if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
		{
			NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
			SendFailMarketItemBuy(pUser, ACK_DB_ERROR);
			DEBUGLOG("CS_MARKET_ITEM_BUY : false == NLogic::NFunction::SendMail");
			return;
		}

		NLogic::NFunction::ModifyGold(pUser, pTradeItem->GetData().item_price * -1);
		NGameLog::LogGoldInfo(pUser, BUY_TRADE, pTradeItem->GetData().item_price * -1);
	}

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << pTradeItem->GetData().reg_user_seq;
	*pAck << pUser->GetCharacterInfo().gold;
	*pAck << pUser->GetVirtualCurrency()->GetZen();
	pAck->MakePacket(CMD_SC_MARKET_ITEM_BUY);
	pUser->Send(pAck);

	// 판매자에게 Noti.
	::ProjectZ::NProxy::TradeItemSoldout(pUser,
			pTradeItem->GetData().reg_user_seq,
			pTradeItem->GetTradeSeq(),
			pTradeItem->GetData().item.class_type,
			pTradeItem->GetData().item.sub_type);

	// 구매 HISTORY 저장
	NGameLog::LogTradeBuyInfo(pUser,
			pTradeItem->GetData().reg_user_seq,
			pTradeItem->GetData().item_price,
			pTradeItem->GetData().item.class_type,
			pTradeItem->GetData().item.sub_type,
			pTradeItem->GetTradeSeq(),
			static_cast<uint64_t>(pTradeItem->GetData().reg_date),
			pTradeItem->GetData().item.quality,
			itemName.c_str());

	// 반환
	NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
}

} /*NCommand*/ } /*ProjectZ*/
